package com.SpringIoc.test_1_25_springioc_and_di;

public class Introduce {
    //**** 什么是 Spring ****
    // Spring 是一个包含众多工具的 IoC 容器
    // Spring 两大核心思想  1.IoC  2. AOP

    // 先学 IOC
    // IoC是什么?
    // IoC 是 控制反转
    //先说 什么是容器?
    //  list/map 是一个装数据的容器
    //  tomcat  是一个 web 容器
    //  Spring 容器, 装的是一个对象

    // ****详解 IoC, 控制反转****
    // 拆开来猜, 就是 控制权反转
    // 那么是拥有的谁的权呢?
    //  创建对象的控制权, 这个就是使用者来创建的
    //  接下来反转了, 那就不由之前的使用者来创建了
    // 而是交给 Spring 来创建了
    // 这就是 IoC 的理解

    // 既然是容器, 呢么Spring 应该具备两种功能, 那就是 取出对象, 跟创建对象
    // 这就是 Spring 在 IoC 这一块的功能

    // 就像 自动驾驶汽车, 本来是由人来控制汽车的, 现在是自动驾驶了, 而是由汽车系统控制的,交给他们了,这也就是另一种 控制反转
    // 所以 控制反转 体现的是一种思想

    // 在Controller层中 或者其他代码
    // 加了注解之后 就是 体现到 控制反转的应用了

    // 在制造汽车呢连个包里面
    // 有更好的 Spring的 IoC 的 解释
    // Spring 就是帮我们创建各种各样的对象, 或者是管理对象
    // 而我们只需要做的,告诉Spring,帮我们管理哪些对象, 知道如何取出来这些对象


    // 接下来看看 DI
    // IoC 是一种思想, 那么 DI 就是一种实现方式
    // DI 就是依赖注入
    // 也就是更简单更方便的方式, 把这个依赖注入到这个对象

    // **** IoC 详解 ****
    // ****  Bean的存储 ****
    // Spring 是一个容器, 存的是对象, 对象这个词, 在 Spring 的范围内, 称之为 bean
    // (Spring 管理的对象 就称之为 bean , 这也是 限制在 Spring 范围内这样称呼)
    // 所以呢 IoC 控制反转 中 的控制权也就是 bean 的控制权, 也就是对象的控制权 进行了反转
    // 之前项目中依赖的对象需要自己去创建, 有了 Spring 之后就不需要自己去创建了, 而是通过Spring 来创建
    // **** 控制反转其优点就是: 解耦 ****
    // 上面的这个IoC的 Spring 指的是 Spring Core 或者 Spring Framework
    // 而用 Spring 做的项目 指的是 Spring 全家桶
    // Maven 只是一个项目管理工具
    // 有了Maven 之后 用Maven 来管理jar包
    // 后来有了注解之后就不用在配置了

    // **** IoC 提供了 两类注解 ****
    // 共有两类注解类型可以实现：
    // Bean的存
    //1. 类注解：@Controller、@Service、@Repository、@Component、@Configuration. (五大注解)
    //2. ⽅法注解：@Bean.

    // 现在分别来解释:
    // @Controller（控制器存储）(Controller层)
    //  @Service（服务存储）   (Service层)
    // @Repository（仓库存储） (持久层:或者叫:Dao层)
    // @Component（组件存储）  (其他层)
    // @Configuration（配置存储） (其他层)

    // **** 为什么要这么多类注解？ ****
    // 这个也是和咱们前⾯讲的应⽤分层是呼应的. 让程序员看到类注解之后，就能直接了解当前类的⽤途.
    //• @Controller：控制层, 接收请求, 对请求进⾏处理, 并进⾏响应.
    //• @Service：业务逻辑层, 处理具体的业务逻辑.
    //• @Repository：数据访问层，也称为持久层. 负责数据访问操作
    //• @Configuration：配置层. 处理项⽬中的⼀些配置信息

    //  **** 类注解之间的关系 ****
    // 除了 Component 这个注解, 其他四个注解都是 Component 的衍生类
    // 就是 根据 Component 来变化的其他类, 他们是父子关系
    // 他们四个底层的实现都是 Component
    // 除此之外 Controller 被赋予了额外的功能, 如果想要被外界访问到 就必须用到 Controller 注解
    // 但是 为什么其他里面的代码也有一样的为什么不能实现呢?
    // 这就是注解内部的含义了
    // 比如 Controller 能否使用 Service 来代替的取接收请求呢?
    // 不可以, 结果在返回网页的时候会报错
    // 是因为, Spring在这些注解中做出了特殊处理
    // 所以想要接收请求的时候 只能使用 Controller 注解

    // 这五大注解只能加在类上, 并且只能加在自己的代码上
    // 如果引入了一个第三方的 Jar 包, 也希望交给 Spring 管理, 是没有 办法加五大注解的
    // 那么可以使用 @Bean 注解
    // @Bean 是方法注解 (这是第一个应用场景)



    // 还有第二个应用场景
    // 那就是: 对于一个类, 定义多个对象时, 比如数据库的操作, 定义多个数据源
    //       如果只使用,类注解,那么拿到的只是同一个
    //    这时候就要用 Bean 注解

    // 1.@Bean 一定要搭配五大注解来使用

    // 2.从这里看出来, 在使用 @Bean 注解时, bean 的名称是 方法名
    //   而且 当 一个类型 存在多个Bean 时, 我们就不能使用 类型来获取对象了
    //   必须要使用名称来获取, 或者使用 名称 + 类型的方式获取

    // 3.@Bean 传递参数, 定义了 一个 叫 name 的 String 类型的对象
    //   第二个 定义了一个 叫 name1 的 String 类型的对象
    //   这时候就会根据名称取拿的
    //   如果当前需要的Bean的雷响, 对应的对象只有一个时 就直接赋值了
    //   如果有多个时, 就通过名称去匹配

    // Spring 还有一个特殊的特点: 约定要大于配置
    // Spring可以要做到0配置, 正式因为事先约定好了
    // 就比如: 现在把 启动类 移动到 Controller包里面的话, 运行就会报错, 只能扫描到Controller 注解, 而扫描不到其他的五大注解里面的了
    // 解决方法, 也是可以通过加上一个注解: @ComponentScan("路径"), 可以指定扫描路径
    // 约定就是: 先扫描启动类当前目录, 再扫描他的子目录

    // 约定大于配置的 其中之一的体现: 就是扫描路径(默认扫描路径是: 启动类所在的目录以及其子孙目录)
    //                          可以通过 @ComponentScan("路径") 自己指定扫描路径, 不指定的话就是默认扫描情况




    // **** 详解 DI 依赖注入****
    // 依赖注⼊是⼀个过程，是指IoC容器在创建Bean时, 去提供运⾏时所依赖的资源，⽽资源指的就是对象.
    // 在上⾯程序案例中，我们使⽤了 @Autowired 这个注解，完成了依赖注⼊的操作.
    //简单来说, 就是把对象取出来放到某个类的属性中.
    //在⼀些⽂章中, 依赖注⼊也被称之为 "对象注⼊", "属性装配", 具体含义需要结合⽂章的上下⽂来理解

    // 关于依赖注⼊, Spring也给我们提供了三种⽅式:
    // Bean的取
    //1. 属性注⼊(Field Injection)
    // 在 UserController 包里面的 类种有 @Autowired
    // 去掉这个注解, 就会报空指针异常
    // 而空指针异常报哪一行错了就是呢一行错了, 看 .
    // 这个是最好判断的,
    // 这个注解会把属性注入进来
    // 注入的时候与Bean定义的名称是无所谓的

    // 属性注入以类型进行匹配, 与注入的属性名称无关
    // 但是一个类型存在多个对象时, 会优先名称匹配, 如果名称匹配不上 就会报错

    //2. 构造⽅法注⼊(Constructor Injection)
    // 还是在呢个包里面举例子

    // 如果存在多个构造函数, 需要加上 @Autowired 注明使用哪个构造函数
    // 如果只有一个构造函数, @Autowired 可以省略掉

    //3. Setter 注⼊(Setter Injection)
    // 也需要用到 @Autowired 注解


    // 既然 @Autowired 这么好用
    // 为什么官方还是不推荐呢?
    // 还是再 呢个包里面举例子
    // @Autowired 既然和类型有关与名字无关
    // 还有一个缺点: 这个注解没有办法注入一个 Final 修饰的属性
    // Final 修饰的属性 1.需要再定义的时候进行赋值
    //  2. 构造方法中进行赋值

    // ***** 三种注⼊优缺点分析(八股文) *****
    // 属性注⼊
    //◦ 优点: 简洁，使⽤⽅便；
    //◦ 缺点:
    //▪ 只能⽤于 IoC 容器，如果是⾮ IoC 容器不可⽤，并且只有在使⽤的时候才会出现 NPE（空指针异常）
    //▪ 不能注⼊⼀个Final修饰的属性

    //构造函数注⼊(Spring 4.X推荐)
    //◦ 优点:
    //▪ 可以注⼊final修饰的属性
    //▪ 注⼊的对象不会被修改
    //▪ 依赖对象在使⽤前⼀定会被完全初始化，因为依赖是在类的构造⽅法中执⾏的，⽽构造⽅法
    //  是在类加载阶段就会执⾏的⽅法.
    //▪ 通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的
    //◦ 缺点:
    //▪ 注⼊多个对象时, 代码会⽐较繁琐

    // Setter注⼊(Spring 3.X推荐) // 这不是 SpringBoot的版本, 本 SpringBoot 用的2.X的版本而对应的Spring是5.X
    //◦ 优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
    //◦ 缺点:
    //▪ 不能注⼊⼀个Final修饰的属性
    //▪ 注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险

    // **** @Autowired 常见问题 ****
    // 当程序中 一个 类有多个对象的时候, 使用这个注解的时候就会报错
    // 解决办法: 1. 属性名就要和对象名保持一致
    // 2. 使用@Primary 注解表示默认对象(指定Bean)  (在Config 包中的 BeanConfig 中演示了) (不推荐)
    // 3. 使用@Qualifier 注解, 达到的含义就是和 1 方法的含义一样 (指定Bean的名称) (在 UserController 中演示)
    //      @Qualifier注解不能单独使⽤，必须配合@Autowired使⽤
    // 4. 使用@Resource 注解  (指定Bean的名称) (这个使用率更高)
    // 5. Bean重命名,指定Bean

    // 常⻅⾯试题:
    //  @Autowired 与 @Resource的区别
    //• @Autowired 是spring框架提供的注解，⽽@Resource是JDK提供的注解
    //• @Autowired 默认是按照类型注⼊(这里要说全)，⽽@Resource是按照名称注⼊.  (这一行必须要知道)
    // 相⽐于 @Autowired 来说，
    //@Resource ⽀持更多的参数设置，例如 name 设置，根据名称获取 Bean。

    // IoC 要解决的事情就是, 属性的注入的问题, 属性是跟对象联系的





    // **** ApplicationContext VS BeanFactory（常⻅⾯试题） ****
    //• 继承关系和功能⽅⾯来说：Spring 容器有两个顶级的接⼝：BeanFactory 和
    //ApplicationContext。其中 BeanFactory 提供了基础的访问容器的能⼒，⽽
    //ApplicationContext 属于 BeanFactory 的⼦类，它除了继承了 BeanFactory 的所有功能之外，
    //它还拥有独特的特性，还添加了对国际化⽀持、资源访问⽀持、以及事件传播等⽅⾯的⽀持.
    //• 从性能⽅⾯来说：ApplicationContext 是⼀次性加载并初始化所有的 Bean 对象，⽽
    //BeanFactory 是需要那个才去加载那个，因此更加轻量. (空间换时间)

    // 代码格式化快捷键 : ctrl+alt+l


    // ******* Spring, Spring Boot 和Spring MVC的关系以及区别 ******
    // Spring: 简单来说, Spring 是⼀个开发应⽤框架，什么样的框架呢，有这么⼏个标签：轻量级、⼀
    //站式、模块化，其⽬的是⽤于简化企业级应⽤程序开发.
    //Spring的主要功能: 管理对象，以及对象之间的依赖关系, ⾯向切⾯编程, 数据库事务管理, 数据访
    //问, web框架⽀持等.
    //但是Spring具备⾼度可开放性, 并不强制依赖Spring, 开发者可以⾃由选择Spring的部分或者全
    //部, Spring可以⽆缝继承第三⽅框架, ⽐如数据访问框架(Hibernate 、JPA), web框架(如Struts、
    //JSF)

    // Spring MVC: Spring MVC是Spring的⼀个⼦框架, Spring诞⽣之后, ⼤家觉得很好⽤, 于是按照MVC
    //模式设计了⼀个 MVC框架(⼀些⽤Spring 解耦的组件), 主要⽤于开发WEB应⽤和⽹络接⼝，所以,
    //Spring MVC 是⼀个Web框架.
    //Spring MVC基于Spring进⾏开发的, 天⽣的与Spring框架集成. 可以让我们更简洁的进⾏Web层
    //开发, ⽀持灵活的 URL 到⻚⾯控制器的映射, 提供了强⼤的约定⼤于配置的契约式编程⽀持, ⾮常
    //容易与其他视图框架集成，如 Velocity、FreeMarker等

    // Spring Boot: Spring Boot是对Spring的⼀个封装, 为了简化Spring应⽤的开发⽽出现的，中⼩型
    //企业，没有成本研究⾃⼰的框架, 使⽤Spring Boot 可以更加快速的搭建框架, 降级开发成本, 让开发
    //⼈员更加专注于Spring应⽤的开发，⽽⽆需过多关注XML的配置和⼀些底层的实现.
    //Spring Boot 是个脚⼿架, 插拔式搭建项⽬, 可以快速的集成其他框架进来.
    //⽐如想使⽤SpringBoot开发Web项⽬, 只需要引⼊Spring MVC框架即可, Web开发的⼯作是
    //SpringMVC完成的, ⽽不是SpringBoot, 想完成数据访问, 只需要引⼊Mybatis框架即可.
    //Spring Boot只是辅助简化项⽬开发的, 让开发变得更加简单, 甚⾄不需要额外的web服务器, 直接
    //⽣成jar包执⾏即可

    //最后⼀句话总结: Spring MVC和Spring Boot都属于Spring，Spring MVC 是基于Spring的⼀个
    //MVC 框架，⽽Spring Boot 是基于Spring的⼀套快速开发整合包.

    // 常见的面试题
    // 常⻅⾯试题
    //1) 三种注⼊⽅式的优缺点(参考上⾯课件内容)
    //2) 常⻅注解有哪些? 分别是什么作⽤?
    //web url映射: @RequestMapping
    //参数接收和接⼝响应: @RequestParam, @RequestBody, @ResponseBody
    //bean的存储: @Controller, @Service, @Repository, @Component, @Configuration,
    //@Bean
    //bean的获取: @Autowired, @Qualifier, @Resource
    //3) @Autowired 和@Resource 区别
    //4) 说下你对Spring, SpringMVC, Springboot的理解
    // 这个 Spring 指的是最原生的 Spring



}
